home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / misc / elcheapofax.lha / asc2fax.c < prev    next >
C/C++ Source or Header  |  1993-05-28  |  9KB  |  442 lines

  1. /*
  2.  * asc2fax.c
  3.  *
  4.  * Copyright (C) 1993 by Olaf 'Rhialto' Seibert. All rights reserved.
  5.  *
  6.  * V24.05.93: Initial release
  7.  * V29.05.93: Fixed unsigned character bug
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #define INTUI_V36_NAMES_ONLY
  16. #include <utility/tagitem.h>
  17. #include <intuition/intuition.h>
  18. #include <clib/exec_protos.h>
  19. #include <clib/alib_protos.h>
  20. #include <clib/graphics_protos.h>
  21. #include <clib/intuition_protos.h>
  22. #include <clib/diskfont_protos.h>
  23.  
  24. #include "faxfile.h"
  25.  
  26. #define RASTERWIDTH LINE_BITS
  27. #define ESC        "\33"
  28. #define CSI        "\233"
  29. #define uchar(x)    ((unsigned char)(x))
  30.  
  31. int        verbose;
  32. int        xoffset = 50;
  33. int        yoffset = 50;
  34. int        invert;
  35. void           *IntuitionBase;
  36. void           *GfxBase;
  37. void           *DiskFontBase;
  38. struct BitMap    BitMap;
  39. struct RastPort EmergencyRastPort;
  40. struct RastPort *RastPort;
  41. struct Window  *Window;
  42. struct TextFont *Font;
  43. struct TextFont *OldFont;
  44. struct NewWindow NewWindow = {
  45.     0, 20,            /* LeftEdge, TopEdge */
  46.     640, 0,            /* Width, Height (calculated and set) */
  47.     1, 1,            /* DetailPen, BlockPen */
  48.     0,                /* IDCMPFlags */
  49.     WFLG_SUPER_BITMAP | WFLG_GIMMEZEROZERO | WFLG_NOCAREREFRESH |
  50.     WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBRIGHT, /* Flags */
  51.     NULL,            /* FirstGadget */
  52.     NULL,            /* CheckMark */
  53.     NULL,            /* Title */
  54.     NULL,            /* Screen */
  55.     &BitMap,            /* BitMap */
  56.     20,20, -1,0,        /* Min/Max Width/Height */
  57.     WBENCHSCREEN        /* Type */
  58. };
  59. struct TagItem TextTags[] = {
  60.     TA_DeviceDPI, X_DPI | Y_DPI << 16,
  61.     TAG_END
  62. };
  63. struct TTextAttr TextAttr = {
  64.     "courier.font", 30, FSF_TAGGED, 0, TextTags
  65. };
  66.  
  67. void
  68. meminvert(unsigned char *d, int size)
  69. {
  70.     if (((long) d & 0x01) == 0) {
  71.     while (size >= 4) {
  72.         *(long *)d ^= 0xFFFFFFFF;
  73.         d += 4;
  74.         size -= 4;
  75.     }
  76.     }
  77.     while (size > 0) {
  78.     *d++ ^= 0xFF;
  79.     size--;
  80.     }
  81. }
  82.  
  83. struct TextInfo {
  84.     struct RastPort *rp;
  85.     int         xoffset;
  86. } ti;
  87.  
  88. unsigned char  *
  89. DoText(unsigned char *text, int len)
  90. {
  91.     if (len > 0)
  92.     Text(ti.rp, text, len);
  93.     return text + len;
  94. }
  95.  
  96. unsigned char  *
  97. DoCSI(unsigned char *text)
  98. {
  99.     int         arg[8];
  100.     int         narg = 0;
  101.     int         i;
  102.  
  103.     memset(arg, 0, sizeof(arg));
  104.     /* CSI 0 x and CSI x are indistinguishable */
  105.     for(;;text++) {
  106.     while (isdigit(text[0])) {
  107.         if (narg < 8) {
  108.         arg[narg] *= 10;
  109.         arg[narg] += text[0] - '0';
  110.         }
  111.         text++;
  112.     }
  113.     narg++;
  114.     if (text[0] != ';')
  115.         break;
  116.     }
  117.     if (narg > 8)
  118.     narg = 8;
  119.  
  120.     switch (*text++) {
  121.     case 'm':   /* Select graphic rendition */
  122.     for (i = 0; i < narg; i++) {
  123.         switch (arg[i]) {
  124.         case 0:    /* plain */
  125.         SetSoftStyle(ti.rp, FS_NORMAL, FSF_BOLD|FSF_ITALIC|FSF_UNDERLINED);
  126.         SetDrMd(ti.rp, JAM1);
  127.         break;
  128.         case 1:    /* bold */
  129.         SetSoftStyle(ti.rp, FSF_BOLD, FSF_BOLD);
  130.         break;
  131.         case 3:    /* italic */
  132.         SetSoftStyle(ti.rp, FSF_ITALIC, FSF_ITALIC);
  133.         break;
  134.         case 4:    /* underline */
  135.         SetSoftStyle(ti.rp, FSF_UNDERLINED, FSF_UNDERLINED);
  136.         break;
  137.         case 7:    /* inverse video */
  138.         SetDrMd(ti.rp, JAM1 | INVERSVID);
  139.         break;
  140.         case 22:     /* not bold */
  141.         SetSoftStyle(ti.rp, 0, FSF_BOLD);
  142.         break;
  143.         case 23:     /* not italic */
  144.         SetSoftStyle(ti.rp, 0, FSF_ITALIC);
  145.         break;
  146.         case 24:     /* not underline */
  147.         SetSoftStyle(ti.rp, 0, FSF_UNDERLINED);
  148.         break;
  149.         case 27:     /* not inverse video */
  150.         SetDrMd(ti.rp, JAM1);
  151.         break;
  152.         }
  153.     }
  154.     break;
  155.     case 'x':           /* set left offset */
  156.     ti.xoffset = arg[0];
  157.     break;
  158.     }
  159.  
  160.     return text;
  161. }
  162.  
  163. unsigned char  *
  164. DoCtrl(unsigned char *text)
  165. {
  166.     switch (*text++) {
  167.     case '\t':          /* tab */
  168.     {
  169.         int         charpos;
  170.  
  171.         charpos = (ti.rp->cp_x - ti.xoffset) / ti.rp->TxWidth;
  172.         charpos = (charpos + 8) & ~7;
  173.         Move(ti.rp, ti.xoffset + charpos * ti.rp->TxWidth, ti.rp->cp_y);
  174.     }
  175.     break;
  176.     case '\n':          /* newline */
  177.     Move(ti.rp, ti.xoffset, ti.rp->cp_y + ti.rp->TxHeight);
  178.     break;
  179.     case '\f':          /* formfeed */
  180.     SetRast(ti.rp, 0);
  181.     Move(ti.rp, ti.xoffset, ti.rp->TxBaseline);
  182.     break;
  183.     case uchar('\233'): /* control sequence introducer */
  184.     goto csi;
  185.     case '\033':        /* escape */
  186.     switch (*text++) {
  187.     case 'c':       /* reset */
  188.         ti.xoffset = 0;
  189.         ti.rp->Mask = 0x0001;
  190.         SetAPen(ti.rp, 1);
  191.         SetBPen(ti.rp, 0);
  192.         DoCtrl("\f");
  193.         DoCSI("0m");
  194.         break;
  195.     case '[':       /* CSI */
  196.     csi:
  197.         text = DoCSI(text);
  198.         break;
  199.     }
  200.     break;
  201.     }
  202.  
  203.     return text;
  204. }
  205.  
  206. void
  207. WinWrite(unsigned char *text)
  208. {
  209.     while (*text) {
  210.     unsigned char  *p;
  211.     int        len;
  212.  
  213.     /* First, determine how much real text we have */
  214.     for (len = 0, p = text; isprint(*p); p++) {
  215.         len++;
  216.     }
  217.     text = DoText(text, len);
  218.     if (*text && !isprint(*text))
  219.         text = DoCtrl(text);
  220.     }
  221. }
  222.  
  223. void
  224. WinWriteInit(struct RastPort *rp)
  225. {
  226.     ti.rp = rp;
  227.     DoCtrl(ESC"c");
  228. }
  229.  
  230.  
  231. long
  232. dofile(char *ascname, void *faxp)
  233. {
  234.     unsigned char   line[256];
  235.     FILE       *file;
  236.     struct RastPort *rp = RastPort;
  237.  
  238.     file = fopen(ascname, "r");
  239.     if (file == NULL) {
  240.     printf("Can't open file %s.\n", ascname);
  241.     return 1;
  242.     }
  243.  
  244.     faxout_begin_page(faxp, 1);
  245.  
  246.     WinWriteInit(RastPort);
  247.     /* reset, set x offset */
  248.     sprintf(line, ESC"c" CSI"%dx", xoffset);
  249.     WinWrite(line);
  250.  
  251.     if (yoffset) {
  252.     int        i;
  253.  
  254.     for (i = 0; i < yoffset; i++)
  255.         tofax(faxp, BitMap.Planes[0], RASTERWIDTH);
  256.     }
  257.  
  258.     for (;;) {
  259.     int        i;
  260.     unsigned char  *plane;
  261.  
  262.     if (feof(file))
  263.         break;
  264.     if (fgets(line, sizeof(line), file) == NULL)
  265.         break;
  266.     if (plane = strchr(line, '\n'))
  267.         *plane = '\0';
  268.  
  269.     if (verbose)
  270.         printf("%s\n", line);
  271.     WinWrite("\f");
  272.     WinWrite(line);
  273.  
  274.     SyncSBitMap(rp->Layer);
  275.     plane = BitMap.Planes[0];
  276.     for (i = 0; i < Font->tf_YSize; i++) {
  277.         if (invert)
  278.         meminvert(plane, BitMap.BytesPerRow);
  279.         tofax(faxp, plane, RASTERWIDTH);
  280.         plane += BitMap.BytesPerRow;
  281.     }
  282.     }
  283.  
  284.     faxout_end_page(faxp);
  285.     fclose(file);
  286.  
  287.     return 0;
  288. }
  289.  
  290. void
  291. openall(void)
  292. {
  293.     /* Libraries */
  294.     IntuitionBase = OpenLibrary("intuition.library", 33);
  295.     if (IntuitionBase == NULL) {
  296.     printf("Needs intuition V33+.\n");
  297.     exit(10);
  298.     }
  299.     GfxBase = OpenLibrary("graphics.library", 33);
  300.     if (GfxBase == NULL) {
  301.     printf("Needs gfx V33+.\n");
  302.     exit(10);
  303.     }
  304.     DiskFontBase = OpenLibrary("diskfont.library", 34);
  305.     if (DiskFontBase == NULL) {
  306.     printf("Needs diskfont V34+.\n");
  307.     exit(10);
  308.     }
  309.     /* Font for window; sorry for the strange order */
  310.     printf("Opening DiskFont... (This may take a while)\n");
  311.     Font = OpenDiskFont((struct TextAttr *)&TextAttr);
  312.     if (Font == NULL) {
  313.     printf("No %s %d!\n", TextAttr.tta_Name, TextAttr.tta_YSize);
  314.     exit(10);
  315.     }
  316.     NewWindow.Height = Font->tf_YSize + 16;  /* slight safety fudge */
  317.     /* Raster for text */
  318.     InitBitMap(&BitMap, 1, RASTERWIDTH, NewWindow.Height);
  319.     if ((BitMap.Planes[0] = AllocRaster(RASTERWIDTH, NewWindow.Height)) == NULL) {
  320.     printf("No plane\n");
  321.     exit(10);
  322.     }
  323.     /* Window for raster. For showing-off purposes only. */
  324.     if ((Window = OpenWindow(&NewWindow)) == NULL) {
  325.     printf("No window (probably too large). Will do without.\n");
  326.     }
  327.     if (Window) {
  328.     RastPort = Window->RPort;
  329.     } else {
  330.     RastPort = &EmergencyRastPort;
  331.     InitRastPort(RastPort);
  332.     RastPort->BitMap = &BitMap;
  333.     }
  334.     RastPort->Mask = 0x0001;
  335.     OldFont = RastPort->Font;
  336.     SetFont(RastPort, Font);
  337. }
  338.  
  339.  
  340. /*
  341.  * Clean up system stuff in case of exit
  342.  */
  343. void
  344. cleanup(void)
  345. {
  346.     if (Font) {
  347.     SetFont(RastPort, OldFont);
  348.     CloseFont(Font);
  349.     }
  350.     if (Window) {
  351.     CloseWindow(Window);
  352.     }
  353.     if (GfxBase) {
  354.     if (BitMap.Planes[0]) {
  355.         FreeRaster(BitMap.Planes[0], RASTERWIDTH, NewWindow.Height);
  356.         BitMap.Planes[0] = NULL;
  357.     }
  358.     CloseLibrary(GfxBase);
  359.     }
  360.     if (IntuitionBase) {
  361.     CloseLibrary(IntuitionBase);
  362.     }
  363.     if (DiskFontBase) {
  364.     CloseLibrary(DiskFontBase);
  365.     }
  366. }
  367.  
  368. int
  369. main(int argc, char **argv)
  370. {
  371.     char       *outfile = "ascii.g3";
  372.     struct faxout  *faxp;
  373.     int         rawfax = 1;
  374.     int         append = 0;
  375.     extern char    *optarg;
  376.     extern int        optind;
  377.     extern int        getopt(int, char **, char *);
  378.     int         errflg = 0;
  379.     int         c;
  380.  
  381.     while ((c = getopt(argc, argv, "af:io:rs:vx:y:")) != -1) {
  382.     switch (c) {
  383.     case 'a':
  384.         append = 1;
  385.         break;
  386.     case 'f':
  387.         TextAttr.tta_Name = optarg;
  388.         break;
  389.     case 's':
  390.         TextAttr.tta_YSize = atoi(optarg);
  391.         break;
  392.     case 'i':
  393.         invert = 1;
  394.         break;
  395.     case 'o':
  396.         outfile = optarg;
  397.         break;
  398.     case 'r':
  399.         rawfax++;
  400.         break;
  401.     case 'v':
  402.         verbose = TRUE;
  403.         break;
  404.     case 'x':
  405.         xoffset = atoi(optarg);
  406.         break;
  407.     case 'y':
  408.         yoffset = atoi(optarg);
  409.         break;
  410.     case '?':
  411.         errflg++;
  412.         break;
  413.     }
  414.     }
  415.  
  416.     if (errflg || optind >= argc) {
  417.     printf(
  418. "Usage: asc2fax [-o fax-file (ascii.g3)] [-r raw faxfile] [-a (append)]\n"
  419. "               [-x/y x/y-offset (50)] [-v] [-i (invert)]\n"
  420. "               [-f name.font] [-s fontsize] ascii-files\n");
  421.     exit(EXIT_FAILURE);
  422.     }
  423.  
  424.     atexit(cleanup);
  425.     openall();
  426.  
  427.     faxp = faxout_open_fp(fopen(outfile, append? "ab": "wb"), rawfax);
  428.     if (faxp == NULL) {
  429.     fprintf(stderr, "can't open output file %s.\n", outfile);
  430.     goto fail;
  431.     }
  432.  
  433.     while (optind < argc) {
  434.     dofile(argv[optind], faxp);
  435.     optind++;
  436.     }
  437.  
  438.     faxout_close(faxp);
  439. fail:
  440.     /* atexit function cleans up here */
  441. }
  442.